package ip

import (
	"fmt"
	"gitee.com/liumou_site/logger"
	"github.com/spf13/cast"
	"net"
	"strings"
)

// SliceToString 字符串列表转字符串(seq: 拼接符,可以用: 空格 / _  @ 之类,具体请以实际需求设置)
//
//	示例: SliceToString([]string{"1", "2", "3"}, "|")
//
// 返回
//
//	"1|2|3"
func SliceToString(ls []string, sep string) string {
	var result string
	for index, i := range ls {
		if index == 0 {
			result = cast.ToString(i)
		} else {
			result += sep + cast.ToString(i)
		}
	}
	return result
}

// StrListToIpList 将字符串列表转换为IP地址列表。
// 它接受一个字符串切片作为输入，每个字符串代表一个IP地址。
// 对于每个有效的IP地址字符串，它会尝试解析成net.IP类型，
// 并将解析成功的IP地址添加到结果切片中。
// 最终返回一个net.IP类型的切片，包含所有解析成功的IP地址。
// 示例:
//
//	StrListToIpList([]string{"192.168.1.1", "192.168.1.2", "192.168.1.3"})
//
// 返回
//
//	[]net.IP{"192.168.1.1", "192.168.1.2", "192.168.1.3"}
func StrListToIpList(ips []string) []net.IP {
	var res []net.IP         // 初始化结果切片
	for _, ip := range ips { // 遍历输入的字符串切片
		ip_ := net.ParseIP(ip) // 尝试解析IP地址
		if ip_ != nil {        // 如果解析成功
			res = append(res, ip_) // 将解析成功的IP地址添加到结果切片中
		}
	}
	return res // 返回结果切片
}

// CompareS 比较两个IP地址的特定字节是否满足条件。
// max: 较大的IP地址
// mini: 较小的IP地址
// sip: 要比较的IP地址的字节层级（1~4）,如果上一个层级比较大于mini的字节则直接返回true
// 返回值: 如果max的字节大于等于mini的字节则返回true，否则返回false。
//
//	如果sip不在1~4范围内，则返回错误。
func CompareS(maxIp, miniIp net.IP, sip uint8) (bool, error) {
	if maxIp.Equal(miniIp) {
		logger.Debug("两个IP地址相等: ", maxIp, " = ", miniIp)
		return true, nil
	}
	max_ := toInt(maxIp)
	mini := toInt(miniIp)
	if sip == 1 {
		return max_[0] >= mini[0], nil // 比较第一个字节
	}
	if sip == 2 {
		if max_[0] >= mini[0] { // 比较第一个字节
			return true, nil
		}
		return max_[1] >= mini[1], nil // 比较第二个字节
	}
	if sip == 3 {
		if max_[0] >= mini[0] { // 比较第一个字节
			return true, nil
		}
		if max_[1] >= mini[1] { // 比较第一个字节
			return true, nil
		}
		return max_[2] >= mini[2], nil // 比较第三个字节
	}
	if sip == 4 {
		if max_[0] >= mini[0] { // 比较第一个字节
			return true, nil
		}
		if max_[1] >= mini[1] { // 比较第一个字节
			return true, nil
		}
		if max_[2] >= mini[2] { // 比较第一个字节
			return true, nil
		}
		return max_[3] >= mini[3], nil // 比较第四个字节
	}
	return false, fmt.Errorf("层级范围错误: 1~4") // sip不在1~4范围内，返回错误
}

// Compare 比较两个 net.IP 类型的 IP 地址，
// 示例:
//
//	Compare(net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2"))
//
// 返回值: 如果 max 大于 mini，则返回 true，否则返回 false。
func Compare(max, mini net.IP) bool {
	// 首先检查 IP 地址是否为空
	if max == nil || mini == nil {
		logger.Error("IP地址为空")
		return false
	}
	if max.Equal(mini) {
		logger.Debug("两个IP地址相等")
		return false
	}
	max_ := toInt(max)
	mini_ := toInt(mini)
	//logger.Debug(max_)
	//logger.Debug(mini_)
	//logger.Debug(max_[0], mini_[0])
	if max_[0] > mini_[0] {
		logger.Debug(max, ">", mini)
		logger.Debug("max[0] > mini[0]")
		return true
	}
	//logger.Debug(max_[1], mini_[1])
	if max_[1] > mini_[1] {
		logger.Debug(max, ">", mini)
		//logger.Debug("max[0] == mini[0] && max[1] > mini[1]")
		return true
	}
	//logger.Debug(max_[2], mini_[2])
	if max_[2] > mini_[2] {
		logger.Debug(max, ">", mini)
		//logger.Debug("max[0] == mini[0] && max[1] == mini[1] && max[2] == mini[2] && max[3] >= mini[3]")
		return true
	}
	//logger.Debug(max_[3], mini_[3])
	if max_[3] > mini_[3] {
		logger.Debug(max, ">", mini)
		//logger.Debug("max[0] == mini[0] && max[1] == mini[1] && max[2] == mini[2] && max[3] == mini[3]")
		return true
	}
	return false

}

// toInt 将 net.IP 类型的 IP 地址转换为 uint8 类型的切片。
// 这个函数遍历 IP 地址的每个字节，并将其添加到结果切片中。
func toInt(ip net.IP) []uint8 {
	var res []uint8 // 初始化结果切片
	//logger.Debug(ip)
	strs := strings.Split(ip.String(), ".")
	//logger.Debug(strs)
	if len(strs) == 0 {
		logger.Error(fmt.Sprintf("IP地址为空"))
	}

	for _, v := range strs { // 遍历 IP 地址的每个字节
		//logger.Debug(v)
		res = append(res, cast.ToUint8(v)) // 将字节添加到结果切片中
	}
	return res // 返回结果切片
}

// CompareIP 比较两个IPv4地址，返回-1, 0, 1分别表示小于、等于、大于。
func CompareIP(ip1, ip2 net.IP) int {
	for i := 0; i < 4; i++ {
		if ip1[i] < ip2[i] {
			return -1
		} else if ip1[i] > ip2[i] {
			return 1
		}
	}
	return 0
}
